package com.atguigu.gmall.pms.service.impl;

import com.atguigu.gmall.common.consts.GmallConsts;
import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.pms.service.*;
import com.atguigu.gmall.pms.vo.SpuVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.common.bean.PageResultVo;
import com.atguigu.gmall.common.bean.PageParamVo;

import com.atguigu.gmall.pms.mapper.SpuMapper;


@Service("spuService")
public class SpuServiceImpl extends ServiceImpl<SpuMapper, SpuEntity> implements SpuService {

    @Override
    public PageResultVo querySpuByPage(PageParamVo paramVo) {
        IPage<SpuEntity> page = this.page(
                paramVo.getPage(),
                new QueryWrapper<SpuEntity>()
        );

        return new PageResultVo(page);
    }

    @Override
    public PageResultVo querySpuPageByCategory(PageParamVo paramVo, Long categoryId) {
        LambdaQueryWrapper<SpuEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (categoryId != 0) {
            queryWrapper.eq(SpuEntity::getCategoryId, categoryId);
        }
        String keyword = paramVo.getKey();
        //select * from `pms_spu` where category_id=12 and (`id` like '%keyword%' or name like '%keyword%')
        queryWrapper.and(qw -> qw.like(SpuEntity::getId, keyword).or().like(SpuEntity::getName, keyword));
        IPage<SpuEntity> page = this.page(paramVo.getPage(), queryWrapper);

        return new PageResultVo(page);
    }

    @Autowired
    private SpuDescService spuDescService;

    @Autowired
    private SpuAttrValueService spuAttrValueService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //@Transactional //使用动态代理的方式代理业务类对象，动态代理的invoke方法对当前业务方法执行的前后进行了扩展
    @GlobalTransactional//上面一行是使用事务，该行是使用分布式事务
    @Override
    public void saveSpuVo(SpuVo spuVo) {
        //1.保存到spu
        SpuEntity spuEntity = saveSpuEntity(spuVo);  //回滚

        //拿到一些spu的通用属性,方便下面代码使用
        Long spuId = spuEntity.getId();
        String name = spuEntity.getName();
        Long brandId = spuEntity.getBrandId();
        Long categoryId = spuEntity.getCategoryId();

        //2.保存到spu_desc
        spuDescService.saveSpuDesc(spuVo, spuId); //不回滚

        //制造异常用来测试事务的，注掉
        //int i = 1/0;

        //3.保存到spu_attr_value
        spuAttrValueService.saveSpuAttrValue(spuVo, spuId);

        //4.保存到sku, sku_images, sku_attr_value, sku_bounds, sku_full_reduction, sku_ladder
        skuService.saveSkus(spuVo, spuId, name, brandId, categoryId);

        //5.将spuId发送消息到rabbitmq消息队列,search服务会定义交换机接受并消费消息，将新增的spu存入es的数据库中
        rabbitTemplate.convertAndSend(GmallConsts.SAVE_SPU_EXCHANGE_NAME,GmallConsts.SAVE_SPU_ROUTING_KEY,spuId);

    }


    //1.保存到spu
    public SpuEntity saveSpuEntity(SpuVo spuVo) {
        spuVo.setCreateTime(new Date());
        spuVo.setUpdateTime(new Date());
        SpuEntity spuEntity = spuVo;
        this.save(spuEntity);
        return spuEntity;
    }
    //2、3、4都被抽取到各自的业务类里面了


    @Override
    public List<SpuEntity> querySpuPage(PageParamVo paramVo) {
        LambdaQueryWrapper<SpuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SpuEntity::getPublishStatus, 1);
        IPage<SpuEntity> page = this.page(paramVo.getPage(), wrapper);
        return page.getRecords();
    }


}